package logMonitor.utils;

import com.google.gson.Gson;
import logMonitor.dao.LogMonitorDao;
import logMonitor.domain.Message;
import logMonitor.domain.Record;
import logMonitor.domain.Rule;
import org.apache.commons.lang.StringUtils;
import redis.clients.jedis.ShardedJedis;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by lenovo on 2017/12/28.
 */
public class MonitorHandler {
    //定时加载配置文件的标识
    private static boolean reloaded = false;

    //private static Message message = new Message();
    private static List<Rule> ruleListAlive ;
    private static List<Rule> ruleListDead ;

//    static {
//        loadDataModel();
////        //从规则表读取当前的ruleListAlive
////        ruleListAlive = loadRuleAlive();
////        //从规则表读取当前状态是禁用/删除的ruleListDead
////        ruleListDead = loadRuleDead();
//    }
    private static List<Rule> loadRuleAlive(){
//        Rule rule = new Rule();
//        rule.setDst_ip("183.203.65.19");
//        rule.setSrc_ip("10.100.2.86");
//        rule.setExist(true);
//        rule.setValid(true);
//        List<Rule> ruleList = new ArrayList<Rule>();
//        ruleList.add(rule);
        List<Rule> ruleList =  new LogMonitorDao().loadRuleAlive();
        return  ruleList;
    }
    private static List<Rule> loadRuleDead(){
        List<Rule> ruleList =  new LogMonitorDao().loadRuleDead();
        return  ruleList;
    }
    /**
     * 对一行日志进行分割
     * @param line 一行日志
     * @return
     */
    public static Message parser(String line) {
        Message message = new Message();
        String[] messageArr = line.split(" ");
        if(messageArr.length != 8 && messageArr.length != 11){
            return null;
        }
        if(StringUtils.isBlank(messageArr[0]) || !Pattern.matches(".*-.*-.*", messageArr[0])){
            return null;
        }
        try{
            message.setTime(messageArr[0]+" "+messageArr[1]);
            message.setId(messageArr[2]);
            message.setPro(messageArr[3]);
            message.setSrc_ip(messageArr[4]);
            message.setSrc_port(messageArr[5]);
            message.setDst_ip(messageArr[6]);
            message.setDst_port(messageArr[7]);
            message.setFlag(null);
            message.setSeq(null);
            message.setAck(null);
            if(messageArr.length == 11){
                message.setFlag(messageArr[8]);
                message.setSeq(messageArr[9]);
                message.setAck(messageArr[10]);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
//        Message message = new Message();
//        message.setSrc_ip("183.203.65.19");
//        message.setDst_ip("10.100.2.86");
//        message.setPro("tcp");
        return message;
    }

    /**
     * 对message对象进行分析，将分析结果保存到redis
     * @param message
     */
    public static void process(Message message) {
        if(message.getPro()!=null){
            ShardedJedis jedis = null;
            try{
                jedis = MyShardedJedisPool.getShardedJedisPool().getResource();
                if(message.getPro().equals("udp")){
                    String udpKey = "udpAcount" + DateUtils.getDate();
                    //给udp+1
                    jedis.incr(udpKey);
                }
                if(message.getPro().equals("tcp")){
                    String tcpKey = "tcpAcount" + DateUtils.getDate();
                    //给tcp+1
                    jedis.incr(tcpKey);
                }
                //向sortset添加数据
                jedis.zincrby("ipSort",1,message.getSrc_ip());
                jedis.zincrby("ipSort",1,message.getDst_ip());
            }finally {
                if(jedis!=null){
                    jedis.close();
                }
            }
        }
    }

    /**
     * 从规则表读取ruleList，检查每个message，一旦符合规则
     * 就让规则id做大key，源ip:目的ip做小key,存入sortset
     * @param message
     */
    public static void trigger(Message message) {
        if (ruleListAlive == null || ruleListDead == null) {
            loadDataModel();
        }
        ShardedJedis jedis = null;
        try {
            jedis = MyShardedJedisPool.getShardedJedisPool().getResource();
            if(ruleListAlive!=null){
                for(Rule rule : ruleListAlive){
                    if(rule.getSrc_ip()!=null&&!rule.getSrc_ip().equals("")&&!message.getSrc_ip().equals(rule.getSrc_ip()))
                        continue;
                    if(rule.getDst_ip()!=null&&!rule.getDst_ip().equals("")&&!message.getDst_ip().equals(rule.getDst_ip()))
                        continue;
                    if(rule.getSrc_port()!=null&&!rule.getSrc_port().equals("")&&!message.getSrc_port().equals(rule.getSrc_port()))
                        continue;
                    if(rule.getDst_port()!=null&&!rule.getDst_port().equals("")&&!message.getDst_port().equals(rule.getDst_port()))
                        continue;
                    if(rule.getPro()!=null&&!rule.getPro().equals("")&&!message.getPro().equals(rule.getPro()))
                        continue;
                    jedis.zincrby("ruleid:"+rule.getId(),1,message.getSrc_ip()+":"+message.getDst_ip()+":"+rule.getType());
                }
            }
            if(ruleListDead!=null){
                for(Rule rule : ruleListDead){
                    jedis.del("ruleid:"+rule.getId());
                }
            }

        }finally {
            if(jedis!=null){
                jedis.close();
            }
        }


//        如果message的源ip/目的ip符合规则中的ip,就把整个message转成json串，
//        以list形式保存到redis,大key是规则中的ip
//        String tempIP = "127.0.0.1";
//        //message.getDst_ip().equals(tempIP)||message.getSrc_ip().equals(tempIP)
//        if(1==1){
//            //ShardedJedis jedis = null;
//            Gson gson = new Gson();
//            try{
//                jedis = MyShardedJedisPool.getShardedJedisPool().getResource();
//                jedis.rpush(tempIP, gson.toJson(message));
//            }finally {
//                if(jedis!=null){
//                    jedis.close();
//                }
//            }
//        }


    }

    private synchronized static void loadDataModel() {
        if (ruleListAlive == null) {
            ruleListAlive =  new LogMonitorDao().loadRuleAlive();
        }
        if (ruleListDead == null) {
            ruleListDead =  new LogMonitorDao().loadRuleDead();
        }
    }
    /**
     * 配置scheduleLoad重新加载底层数据模型。
     */
    public static synchronized void reloadDataModel() {
        if (reloaded) {
            //从规则表读取当前的ruleList
            ruleListAlive = new LogMonitorDao().loadRuleAlive();
            //从规则表读取当前状态是禁用/删除的ruleListDead
            ruleListDead = new LogMonitorDao().loadRuleDead();
            reloaded = false;
        }
    }

    /**
     * 定时加载配置信息
     * 配合reloadDataModel模块一起使用。
     * 主要实现原理如下：
     * 1，获取分钟的数据值，当分钟数据是10的倍数，就会触发reloadDataModel方法，简称reload时间。
     * 2，reloadDataModel方式是线程安全的，在当前worker中只有一个现成能够操作。
     * 3，为了保证当前线程操作完毕之后，其他线程不再重复操作，设置了一个标识符reloaded。
     * 在非reload时间段时，reloaded一直被置为true；
     * 在reload时间段时，第一个线程进入reloadDataModel后，加载完毕之后会将reloaded置为false。
     */
    public static void scheduleLoad() {
        String date = DateUtils.getDateTime();
        int now = Integer.parseInt(date.split(":")[1]);
        if (now % 2 == 0) {//每10分钟加载一次
            reloadDataModel();
        } else {
            reloaded = true;
        }
    }
}
